package com.mtcarpenter.mall.service.impl;

import com.github.pagehelper.PageHelper;
import com.mtcarpenter.mall.client.CmsSubjectProductRelationClient;
import com.mtcarpenter.mall.client.MemberFeign;
import com.mtcarpenter.mall.common.api.CommonResult;
import com.mtcarpenter.mall.dto.PmsBrandParam;
import com.mtcarpenter.mall.mapper.PmsBrandMapper;
import com.mtcarpenter.mall.mapper.PmsProductMapper;
import com.mtcarpenter.mall.model.PmsBrand;
import com.mtcarpenter.mall.model.PmsBrandExample;
import com.mtcarpenter.mall.model.PmsProduct;
import com.mtcarpenter.mall.model.PmsProductExample;
import com.mtcarpenter.mall.service.PmsBrandService;
import io.seata.spring.annotation.GlobalTransactional;
import org.redisson.RedissonLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 商品品牌Service实现类
 * Created by macro on 2018/4/26.
 */
@Service
public class PmsBrandServiceImpl implements PmsBrandService {
    @Autowired
    private PmsBrandMapper brandMapper;

    @Autowired
    private PmsProductMapper productMapper;

    @Autowired
    private CmsSubjectProductRelationClient cmsSubjectProductRelationClient;

    @Autowired
    private MemberFeign memberFeign;

    @Autowired
    private RedissonClient redissonClient;

    // 自定义分布式事务ID
    @Value("${spring.application.name}")
    private String redissonKey;

    @Autowired
    private RedisTemplate redisTemplate;

    private String redisKey = "test-data";


    @Override
    public List<PmsBrand> listAllBrand() {
        return brandMapper.selectByExample(new PmsBrandExample());
    }

    @Override
    public int createBrand(PmsBrandParam pmsBrandParam) {
        PmsBrand pmsBrand = new PmsBrand();
        BeanUtils.copyProperties(pmsBrandParam, pmsBrand);
        //如果创建时首字母为空，取名称的第一个为首字母
        if (StringUtils.isEmpty(pmsBrand.getFirstLetter())) {
            pmsBrand.setFirstLetter(pmsBrand.getName().substring(0, 1));
        }
        return brandMapper.insertSelective(pmsBrand);
    }

    @Override
    public int updateBrand(Long id, PmsBrandParam pmsBrandParam) {
        PmsBrand pmsBrand = new PmsBrand();
        BeanUtils.copyProperties(pmsBrandParam, pmsBrand);
        pmsBrand.setId(id);
        //如果创建时首字母为空，取名称的第一个为首字母
        if (StringUtils.isEmpty(pmsBrand.getFirstLetter())) {
            pmsBrand.setFirstLetter(pmsBrand.getName().substring(0, 1));
        }
        //更新品牌时要更新商品中的品牌名称
        PmsProduct product = new PmsProduct();
        product.setBrandName(pmsBrand.getName());
        PmsProductExample example = new PmsProductExample();
        example.createCriteria().andBrandIdEqualTo(id);
        productMapper.updateByExampleSelective(product, example);
        return brandMapper.updateByPrimaryKeySelective(pmsBrand);
    }

    @Override
    public int deleteBrand(Long id) {
        return brandMapper.deleteByPrimaryKey(id);
    }

    @Override
    public int deleteBrand(List<Long> ids) {
        PmsBrandExample pmsBrandExample = new PmsBrandExample();
        pmsBrandExample.createCriteria().andIdIn(ids);
        return brandMapper.deleteByExample(pmsBrandExample);
    }

    @Override
    public List<PmsBrand> listBrand(String keyword, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        PmsBrandExample pmsBrandExample = new PmsBrandExample();
        pmsBrandExample.setOrderByClause("sort desc");
        PmsBrandExample.Criteria criteria = pmsBrandExample.createCriteria();
        if (!StringUtils.isEmpty(keyword)) {
            criteria.andNameLike("%" + keyword + "%");
        }
        return brandMapper.selectByExample(pmsBrandExample);
    }

    @Override
    public PmsBrand getBrand(Long id) {
        return brandMapper.selectByPrimaryKey(id);
    }

    @Override
    public int updateShowStatus(List<Long> ids, Integer showStatus) {
        PmsBrand pmsBrand = new PmsBrand();
        pmsBrand.setShowStatus(showStatus);
        PmsBrandExample pmsBrandExample = new PmsBrandExample();
        pmsBrandExample.createCriteria().andIdIn(ids);
        return brandMapper.updateByExampleSelective(pmsBrand, pmsBrandExample);
    }

    @Override
    public int updateFactoryStatus(List<Long> ids, Integer factoryStatus) {
        PmsBrand pmsBrand = new PmsBrand();
        pmsBrand.setFactoryStatus(factoryStatus);
        PmsBrandExample pmsBrandExample = new PmsBrandExample();
        pmsBrandExample.createCriteria().andIdIn(ids);
        return brandMapper.updateByExampleSelective(pmsBrand, pmsBrandExample);
    }

    @Override
    @GlobalTransactional // 开启分布式事务
    public int pmsTestSeata(Long id) {
        System.out.println("pmsTestSeata 开始分布式事务");
        RLock clientLock = redissonClient.getLock(redissonKey + id);
        try {
            clientLock.lock(30, TimeUnit.SECONDS);
            CommonResult commonResult = cmsSubjectProductRelationClient.cmsTestSeata(id);
            System.out.println("pmsTestSeata 第一阶段");
            CommonResult memberUpdate = memberFeign.testMemberUpdate(id);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("pmsTestSeata 出异常");
            return -1;
        } finally {
            try {
                System.out.println("pmsTestSeata 睡会");
                Thread.sleep(20 * 1000L);
                System.out.println("pmsTestSeata 醒来，开始解锁");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            clientLock.unlock();
        }
        System.out.println("pmsTestSeata 第二阶段");
        return 1;
    }

    @Override
    public int pmsTestRedissonLock(Long id) {

        // 设置 testPMSRedissonLock redis参数【非此接口代码】
        redisTemplate.opsForValue().set(redisKey, id);


        System.out.println("pmsTestRedissonLock 开始分布式锁 + 分布式锁");
        System.out.println(redissonKey);
        RLock clientLock = redissonClient.getLock(redissonKey + id);
        try {
            // 加锁
            clientLock.lock(30, TimeUnit.SECONDS);
            System.out.println("pmsTestRedissonLock 加锁逻辑");
            CommonResult commonResult = cmsSubjectProductRelationClient.cmsTestSeata(id);
            CommonResult memberUpdate = memberFeign.testMemberUpdate(id);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("pmsTestRedissonLock 出异常");
            return -1;
        } finally {
            // 解锁
            clientLock.unlock();
            System.out.println("pmsTestRedissonLock 解锁逻辑");
        }
        return 1;
    }

    @Override
    public String testPMSRedissonLock() {
        Long num = -1L;
        RLock test = redissonClient.getLock("test-lock");
        try {
            test.lock(50 * 1000, TimeUnit.SECONDS);
            num = (Long) redisTemplate.opsForValue().get(redisKey);
            if (num > 0) {
                redisTemplate.opsForValue().set(redisKey, --num);
                System.out.println("减库存，剩余：" + num);
            } else {
                System.out.println("库存不足");
            }
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } finally {
            test.unlock();
        }
        return "库存，剩余：" + num;
    }

}
